#include "MSqlConnectionPool.h"
#include "MSqlDatabase.h"

using namespace NsMSql;

QMutex MSqlConnectionPool::m_mutex;
QWaitCondition MSqlConnectionPool::m_waitConnection;

NsMSql::MSqlConnectionPool::MSqlConnectionPool(MSqlDatabase* sqlDatabase)
{
	m_sqlServerAttr = sqlDatabase->getSqlServerAttr();
	m_maxWaitTime = 1000;
	m_waitInterval = 200;

	//初始化连接池
	QString connectionName;
	for (int i = 0; i < m_sqlServerAttr.initialConnectNum; i++)
	{
		MSqlConnection sqlConnection(m_sqlServerAttr);
		connectionName = getConnectionName(m_sqlServerAttr.databaseName, i);
		if (sqlConnection.openConnection(connectionName))    // 有效的连接放入 m_unusedConnectionNames
		{
			m_unusedConnectionNames.enqueue(connectionName);
			m_nameConnectionMap[connectionName] = sqlConnection;
		}
	}
}

NsMSql::MSqlConnectionPool::~MSqlConnectionPool()
{

}

MSqlConnection NsMSql::MSqlConnectionPool::getConnection()
{
	MSqlConnection sqlConnection(m_sqlServerAttr);
	QString connectionName;

	//原子锁
	QMutexLocker locker(&m_mutex);
	// 已创建连接数
	int connectionCount = m_unusedConnectionNames.size() + m_usedConnectionNames.size();
	// 如果连接已经用完，等待 waitInterval 毫秒看看是否有可用连接，最长等待 maxWaitTime 毫秒
	for (int i = 0;
		i < m_maxWaitTime && m_unusedConnectionNames.size() == 0 && connectionCount == m_sqlServerAttr.maxConnectionNum;
		i += m_waitInterval)
	{
		m_waitConnection.wait(&m_mutex, m_waitInterval);
		// 重新计算已创建连接数
		connectionCount = m_unusedConnectionNames.size() + m_usedConnectionNames.size();
	}

	if (m_unusedConnectionNames.size() > 0)
	{
		// 有已经回收的连接，复用它们
		connectionName = m_unusedConnectionNames.dequeue();
		m_usedConnectionNames.enqueue(connectionName);
		sqlConnection = m_nameConnectionMap[connectionName];
	}
	else if (connectionCount < m_sqlServerAttr.maxConnectionNum)
	{
		// 没有已经回收的连接，但是没有达到最大连接数，则创建新的连接,序号从0开始计
		connectionName = getConnectionName(m_sqlServerAttr.databaseName, connectionCount);
		if (sqlConnection.openConnection(connectionName))    // 有效的连接才放入 m_usedConnectionNames
		{
			m_usedConnectionNames.enqueue(connectionName);
			m_nameConnectionMap[connectionName] = sqlConnection;
		}
	}
	else
	{
		// 已经达到最大连接数
		MSqlError(QString("cannot create more connections"));
	}

	return sqlConnection;
}

void NsMSql::MSqlConnectionPool::releaseConnection(MSqlConnection sqlConnection)
{
	QString connectionName = sqlConnection.getConnectionName();

	// 如果是我们创建的连接，从 used 里删除，放入 unused 里
	if (m_usedConnectionNames.contains(connectionName)) {
		QMutexLocker locker(&m_mutex);
		m_usedConnectionNames.removeOne(connectionName);
		m_unusedConnectionNames.enqueue(connectionName);
		m_waitConnection.wakeOne();
	}
}

void NsMSql::MSqlConnectionPool::close()
{
	QMutexLocker locker(&m_mutex);

	// 销毁连接池的时候删除所有的连接
	QMapIterator<QString, MSqlConnection> iter(m_nameConnectionMap);
	while (iter.hasNext()) {
		iter.next();
		MSqlConnection sqlConnection = iter.value();
		sqlConnection.removeConnection();
	}
}

